package org.givwenzen.editors;



import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.internal.core.ResolvedSourceMethod;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.presentation.IPresentationReconciler;
import org.eclipse.jface.text.presentation.PresentationReconciler;
import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
import org.eclipse.jface.text.rules.RuleBasedScanner;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.swt.custom.StyledText;
import org.givwenzen.dialogs.SimpleDialog;
import org.givwenzen.steps.LineParser;
import org.givwenzen.steps.StepLocator;

public class GWZConfiguration extends SourceViewerConfiguration {
	
	private RuleBasedScanner gwzScanner;
	private RuleBasedScanner defaultScanner;
	private ColorManager colorManager;

	public GWZConfiguration(ColorManager colorManager) {
                this.colorManager = colorManager;                
    }
    public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
		return new String[] {
			IDocument.DEFAULT_CONTENT_TYPE,
			GWZPartitionScanner.GWZ_SCRIPT,
			GWZPartitionScanner.GWZ};
	}
    
    @Override
    public IQuickAssistAssistant getQuickAssistAssistant(ISourceViewer sourceViewer) {
        //TODO most likely this is the method we should implement to have quick assist
        return null;
    }
	
	public IHyperlinkDetector[] getHyperlinkDetectors(final ISourceViewer sourceViewer) {	    
	    return new IHyperlinkDetector[] {
	       new IHyperlinkDetector() {
                @Override
                public IHyperlink[] detectHyperlinks(final ITextViewer viewer, final IRegion region, boolean canShowMultipleHyperlinks) {
                    StyledText widget = viewer.getTextWidget();
                    int lineNo = widget.getLineAtOffset(region.getOffset());
                    final int lineOffset = widget.getOffsetAtLine(lineNo);
                    final String line = viewer.getTextWidget().getLine(lineNo);
                    final String step = new LineParser().parse(line);
                    
                    IHyperlink link = new IHyperlink() {

                        @Override
                        public IRegion getHyperlinkRegion() {
                            return new Region(lineOffset, line.length());
                        }

                        @Override
                        public String getHyperlinkText() {
                            return step;
                        }

                        @Override
                        public String getTypeLabel() {
                            return "Go to step";
                        }

                        @Override
                        public void open() {
                            try {
                                //configure search
                                //IProject project = new GivWenZenNatureDetector().detectProject();
                                //TODO: huge hack but I don't know how to get the project the other way 
                                ProjectAwareFastPartitioner partitioner = (ProjectAwareFastPartitioner) viewer.getDocument().getDocumentPartitioner();
                                IProject project = partitioner.getProject();
                                if (project == null) {
                                    new SimpleDialog().show("Cannot locate steps", "I cannot find any project that has GivWenZen nature\n" +
                                    		"Please right-click on the project that contains @DomainSteps and enable 'GivWenZen nature'");
                                    return;
                                }
                              
                                ResolvedSourceMethod methodToJump = new StepLocator().findMethod(step, project);
                                //jump to method
                                if (methodToJump != null) {
                                    JavaUI.openInEditor(methodToJump);
                                    methodToJump = null;
                                } else {
                                    new SimpleDialog().show("Step not found", "There is no step matching this:\n" + step);
                                }
                            } catch ( Exception e ) {
                                throw new RuntimeException(e);
                            }
                        }
                    };
                    return new IHyperlink[] {link};
                }              
	       }
	    };
	}

	private RuleBasedScanner getDefaultScanner() {
		if (defaultScanner == null) {
			defaultScanner = new RuleBasedScanner();
			defaultScanner.setDefaultReturnToken(
				new Token(
					new TextAttribute(
						colorManager.getColor(Colors.DEFAULT))));
		}
		return defaultScanner;
	}
	
	protected RuleBasedScanner getGWZScanner() {
		if (gwzScanner == null) {
			gwzScanner = new RuleBasedScanner();
			gwzScanner.setDefaultReturnToken(
				new Token(
					new TextAttribute(
						colorManager.getColor(Colors.GWZ_KEYWORD))));
		}
		return gwzScanner;
	}

	public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
		PresentationReconciler reconciler = new PresentationReconciler();

		DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getDefaultScanner());
		reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
		reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
		
        dr = new DefaultDamagerRepairer(getGWZScanner());
        reconciler.setDamager(dr, GWZPartitionScanner.GWZ);
        reconciler.setRepairer(dr, GWZPartitionScanner.GWZ);		

		NonRuleBasedDamagerRepairer ndr = new NonRuleBasedDamagerRepairer(
                new TextAttribute(
                    colorManager.getColor(Colors.GWZ_SCRIPT)));
        reconciler.setDamager(ndr, GWZPartitionScanner.GWZ_SCRIPT);
        reconciler.setRepairer(ndr, GWZPartitionScanner.GWZ_SCRIPT);
		
		return reconciler;
	}
	
    public static String getLineString(final ITextViewer viewer,
            final IRegion region) {
        int lineNo = viewer.getTextWidget().getLineAtOffset(region.getOffset());
        String line = viewer.getTextWidget().getLine(lineNo);
        return line;
    }

}